package com.scs.application.modules.dept.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.consts.ParamKeys;
import com.scs.application.consts.SerialKeys;
import com.scs.application.core.entity.DataEntity;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.flow.FlowContext;
import com.scs.application.core.pdf.PdfExportUtils;
import com.scs.application.core.pdf.entity.PdfExportParams;
import com.scs.application.core.pdf.enums.PdfPageDirection;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.CacheUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.core.utils.UtilJava8;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.mapper.MatrMapper;
import com.scs.application.modules.base.mapper.SupplierMapper;
import com.scs.application.modules.base.service.LocationService;
import com.scs.application.modules.base.util.CommonService;
import com.scs.application.modules.cfg.utils.ParameterUtils;
import com.scs.application.modules.dept.entity.Use;
import com.scs.application.modules.dept.entity.UseDtl;
import com.scs.application.modules.dept.mapper.UseMapper;
import com.scs.application.modules.dept.service.UseDtlService;
import com.scs.application.modules.dept.service.UseService;
import com.scs.application.modules.fsd.entity.FsdUser;
import com.scs.application.modules.purchase.enums.PurchaseType;
import com.scs.application.modules.sys.entity.Flow;
import com.scs.application.modules.sys.entity.FlowButton;
import com.scs.application.modules.wm.entity.*;
import com.scs.application.modules.wm.enums.WorkOrderType;
import com.scs.application.modules.wm.mapper.WorkOrderItemMapper;
import com.scs.application.modules.wm.mapper.WorkOrderMapper;
import com.scs.application.modules.wm.service.StockDeptService;
import com.scs.application.modules.wm.service.StockService;
import com.scs.application.modules.wm.service.TertiaryStockService;
import com.scs.application.modules.wm.service.WorkOrderService;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 科室消耗单主表 服务实现类
 * </p>
 */
@Slf4j
@Service
public class UseServiceImpl extends BaseServiceImpl<UseMapper, Use> implements UseService {
    @Autowired
    private UseDtlService useDtlService;
    @Autowired
    private StockService stockService;
    @Autowired
    private SupplierMapper supplierMapper;
    @Autowired
    private WorkOrderMapper workOrderMapper;
    @Autowired
    private WorkOrderItemMapper workOrderItemMapper;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private LocationService locationService;

    @Resource
    private TertiaryStockService tertiaryStockService;

    @Resource
    private MatrMapper matrMapper;
    @Resource
    @Lazy
    private StockDeptService stockDeptService;

    @Override
    public boolean saveOrUpdate(Use entity) {
        // 新增
        if (StringUtils.isBlank(entity.getUseKey())) {
            entity.setUseKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.DEPT_USE_KEY));
        }
        // 获取当前用户科室
        if (StringUtils.isBlank(entity.getDeptId())) {
            entity.setUserName(UserUtils.currentUser().getName())
            .setDeptId(UserUtils.currentUser().getDeptId())
            .setDeptName(UserUtils.currentUser().getDeptName());
        }

        if (StringUtils.isNotBlank(entity.getDeptId()) && StringUtils.isBlank(entity.getDeptName())) {
            Dept dept = (Dept) CacheUtils.get(CacheUtils.BASE_DEPT, entity.getDeptId());
            if (dept == null) {
                throw  new BusinessException( "消耗科室不存在或者已被删除");
            }
            entity.setDeptName(dept.getName());
        }
        return super.saveOrUpdate(entity);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        if(idList.isEmpty()){
            return super.removeByIds(idList);
        }
        // 删除子表
        List<UseDtl> useDtls = useDtlService.list(Wrappers.<UseDtl>query()
                .in("use_id", idList));
        if (!useDtls.isEmpty()){
            useDtlService.removeByIds(useDtls.stream().map(UseDtl::getId).collect(Collectors.toList()));
        }
        // 删除主表
        return super.removeByIds(idList);
    }


    /**
     * 调拨出库产生记账单
     * @param transfer
     * @param transferItems
     */
    @Override
    public void createByTransfer(Transfer transfer, List<TransferItem> transferItems) {
        Use use = new Use();
        use.setRefType("transfer").setRefId(transfer.getId()).setRefKey(transfer.getBusKey()).setRefTable("wm_transfer").setUseKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.DEPT_USE_KEY))
                .setDeptId(transfer.getDeptIdTo()).setDeptName(transfer.getDeptNameTo()).setWarehouseId(transfer.getToWarehouseId())
                .setWarehouseName(transfer.getToWarehouseName()).setFlagUseRedType(0)
                .setUseType("DIST").setUseDate(Calendar.getInstance().getTime())
                .setAmount(transfer.getAmount()).setUserName(UserUtils.currentUser().getName()).setReagentTeamId(transfer.getReagentTeamId())
                .setFlowStatus("end").setFlowModifier(UserUtils.currentUser().getName()).setFlowModified(LocalDateTime.now());
        if (transfer.getType().equals(GlobalConsts.TransferType.returnIn)) { //科室退货入库
            use.setDeptId(transfer.getDeptIdFrom()).setDeptName(transfer.getDeptNameFrom());
            use.setWarehouseId(transfer.getFromWarehouseId()).setWarehouseName(transfer.getFromWarehouseName());
        }

        if (GlobalConsts.TransferType.returnIn.equalsIgnoreCase(transfer.getType())) { //如果是退库的，此时的消耗仓库应该是科室仓库，不应该是中心仓库
            use.setUseType("RETURN").setFlagUseRedType(1).setWarehouseId(transfer.getFromWarehouseId()).setWarehouseName(transfer.getFromWarehouseName());
        }
        this.save(use);

        List<UseDtl> useDtls = Lists.newArrayListWithCapacity(transferItems.size());
        transferItems.forEach(item -> {
            UseDtl useDtl = new UseDtl();
            BeanUtils.copyProperties(item, useDtl);
            useDtl.setUseId(use.getId())
                    .setMatrUnit(item.getSkuUnit())
                    .setSnNo(item.getSn())
                    .setRefId(item.getId())
                    .setUseTime(Calendar.getInstance().getTime())
                    .setSnNo(item.getSn())
                    .setId(null);
            useDtls.add(useDtl);
        });
        useDtlService.saveBatch(useDtls);

        //审核通过
        handlerRedUseFlowEnd(use, transfer.getId());

        //修正，如果是退库的，将库存地修正为退库库存地
        if (GlobalConsts.TransferType.returnIn.equalsIgnoreCase(transfer.getType())) {
            Location location = locationService.getDefaultLocation(transfer.getToWarehouseId());
            stockService.update(Wrappers.<Stock>update().in("sn", transferItems.stream().map(TransferItem::getSn).collect(Collectors.toList()))
                    .set("warehouse_id", transfer.getToWarehouseId()).set("warehouse_name", transfer.getToWarehouseName())
                    .set("location_id", location.getId()).set("location_name", location.getName()));
        }

        //添加三级库库存
        stockDeptService.addByTransfer(transfer,transferItems);
    }

    private void handlerRedUseFlowEnd(Use use, String busId) { //
        FlowContext flowContext1 = new FlowContext();
        FlowButton flowButton1 = new FlowButton();
        Flow flow1 = new Flow();
        flowButton1.setFlagEnd(true).setCode("end");
        flowContext1.setButton(flowButton1);
        flowContext1.setBusEntity(use);
        flow1.setName("审核通过");
        flowContext1.setFlow(flow1);
        flowContext1.setBusId(busId);
        afterHandleFlowChange(flowContext1, use);
    }

    /**
     * 试剂冲红处理
     * @param useDtls 消耗详情
     */
    private void handleRedUseReagent(List<UseDtl> useDtls) {
        List<String> matrIds = useDtls.stream().map(UseDtl::getMatrId).collect(Collectors.toList());
        // 过滤耗材类型为试剂的消耗明细
        List<Matr> matrs = matrMapper.selectList(Wrappers.<Matr>query().in("id", matrIds).eq("base_type", PurchaseType.REAGENT.getKey()));
        if (CollectionUtils.isEmpty(matrs)) { return; }
        List<String> snList = new ArrayList<>();
        for (UseDtl useDtl : useDtls) {
            for (Matr matr : matrs) {
                if (useDtl.getMatrId().equals(matr.getId())) {
                    snList.add(useDtl.getSnNo());
                    break;
                }
            }
        }
        returnReagent(snList);
    }

    private void returnReagent(List<String> snList) {
        // 查询试剂三级库
        List<TertiaryStock> tertiaryStockList = tertiaryStockService.list(Wrappers.<TertiaryStock>query().in("sn", snList));
        if (CollectionUtils.isEmpty(tertiaryStockList)) {
            throw new BusinessException("未找到试剂三级库库存，请确认消耗的试剂来源是否正确");
        } else {
            Date now = new Date();
            for (TertiaryStock tertiaryStock : tertiaryStockList) {
                if (tertiaryStock.getPackageQty() == 0) {
                    throw new BusinessException(String.format("%s已经被消耗，请重新扫描", tertiaryStock.getMatrName()));
                } else {
                    // 试剂三级库扣减库存
                    tertiaryStock.setPackageQty(0.0);
                    tertiaryStock.setSkuQty(0.0);
                    tertiaryStock.setAmount(0.0);
                    tertiaryStock.setMdate(now);
                }
            }
            tertiaryStockService.updateBatchById(tertiaryStockList);
        }
    }

    @Override
    protected void beforeHandleFlowChange(FlowContext flowContext, Use use) {
        super.beforeHandleFlowChange(flowContext, use);
        String buttonKey = flowContext.getButtonKey();
        // 提交审核，不允许空明细提交
        if ("submit".equalsIgnoreCase(buttonKey)) {
            List<UseDtl> useDtls = useDtlService.list(Wrappers.<UseDtl>query().eq("use_id", use.getId()));
            // 重新查询主单据
            use = this.getById(use.getId());
            if (useDtls.isEmpty()){
                throw new BusinessException("科室消耗单%s,请添加明细后提交" , use.getUseKey());
            }

//            String type = useDtlService.getType(use.getId());
//            if (PurchaseType.REAGENT.getKey().equals(type) && StringUtils.isEmpty(use.getReagentTeamId())) {
//                throw new BusinessException("科室消耗单明细包含试剂，请选择试剂组");
//            }

        }

        if (flowContext.isEndNode()) {
            if ("0".equals(use.getFlagUseRedType().toString())) {
                List<UseDtl> useDtls = useDtlService.list(Wrappers.<UseDtl>query().eq("use_id", use.getId()));
                stockService.getExpStockByUC(useDtls.stream().map(UseDtl::getSnNo).collect(Collectors.toList()));
            }
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    protected void afterHandleFlowChange(FlowContext flowContext, Use newEntity) {
        Use entity = flowContext.getBusEntity();
        if(entity.flowModified == null){
            entity.setFlowModified(newEntity.flowModified)
                    .setFlowModifier(newEntity.flowModifier);
        }
        super.afterHandleFlowChange(flowContext, newEntity);
        String buttonKey = flowContext.getButtonKey();
        // 设备科审核确认
        if ("finish".equalsIgnoreCase(buttonKey)) {
            List<String> ids = new ArrayList<>();
            ids.add((entity.getId()));
            CommonService.updatebillFlow(ids, LocalDateTime.now(),true);
        }

        boolean endNode = flowContext.isEndNode();
        if (!endNode) {
            return;
        }

        // 设置明细取用人
        List<UseDtl> useDtls = useDtlService.list(Wrappers.<UseDtl>query().eq("use_id", entity.getId()));
        if (useDtls.isEmpty()){
            throw new BusinessException("消耗出库单没有明细");
        }

        Date date = Date.from( entity.getGmtModified().atZone( ZoneId.systemDefault()).toInstant());
        useDtlService.update(Wrappers.<UseDtl>update()
                .set("user", entity.getModifier()).set("use_time", date).in("use_id", entity.getId()));

        // 生成出库单
        List<WorkOrder> wos = convertUseToOrders(entity);

        List<String> workIds = wos.stream().map(WorkOrder::getId).collect(Collectors.toList());
        workOrderService.postBatch(workIds);

        // 冲红试剂三级库
        if (entity.getFlagUseRedType() == 1) {
            handleRedUseReagent(useDtls);
        }

        CommonService.updateBusTableSnum("dept_use",entity.getId());
        flowContext.setHandledMsg(String.format("科室消耗出库单审核完成，共生成%d个消耗出库单", wos.size()));
        log.info("科室消耗出库单审核完成，共生成{}个科室消耗出库单", wos.size());
        log.info("科室消耗出库单分别为：{}", wos.stream().map(WorkOrder::getBusKey).collect(Collectors.joining(",")));

    }

    @Override
    public List<WorkOrder> convertUseToOrders(Use use) {

        List<UseDtl> useDtls = useDtlService.list(Wrappers.<UseDtl>query().eq("use_id", use.getId()));
        if (useDtls == null || useDtls.size() <1) { throw new BusinessException("消耗明细数量为0"); }
        //根据库存里面的供应商分组，因为耗材供应商可能被修改
        List<String> stockIdList =useDtls.stream().map(UseDtl::getStockId).collect(Collectors.toList());
        List<Stock> stockList;
        if (use.getFlagUseRedType() == 1) {
            stockList = stockService.listStockWithZero(Wrappers.<Stock>query().in("id", stockIdList),null);
        }else {
            stockList = stockService.list(Wrappers.<Stock>query().in("id", stockIdList));
        }
        if (stockList == null) {
            throw new BusinessException("消耗明细所对应的库存在系统中不存在，转换出库单失败");
        }
        if (stockList.size() != useDtls.size()) {
            throw new BusinessException("消耗明细数量【%s】与库存记录库存数量【%s】不一致，转换出库单失败",useDtls.size(),stockList.size());
        }

        //分组去重，条件：供应商，耗材，寄售，一物一码
        List<Stock> stockGroupList = UtilJava8.stockGroup(stockList);
        ArrayList<WorkOrder> orders = Lists.newArrayList();
        stockGroupList.forEach(stockGroup -> {
            WorkOrderKey orderKey = new WorkOrderKey(stockGroup.getSupplierId(), stockGroup.getFlagConsignment(), stockGroup.getFlagOmoc());

            //符合该分组的所有库存
            List<Stock> stockAddList = UtilJava8.stockFilter(stockList,stockGroup);
            WorkOrder order = convertDemandItemsToOrder(orderKey, use, UtilJava8.getWODeptUseItems(stockAddList,useDtls));
            orders.add(order);
        });

        return orders;
    }

    private WorkOrder convertDemandItemsToOrder(WorkOrderKey orderKey,
                                                Use use, List<UseDtl> useDtls) {

        String supplierId = orderKey.supplierId;
        Supplier supplier = supplierMapper.selectById(supplierId);
        if (supplier == null) {
            log.error("转换出库单失败，消耗单号：{}，供应商 {} 不存在", use.getUseKey(), supplierId);
            throw new BusinessException("转换科室配送出库单失败");
        }

        // 出库金额求和
        double sum = useDtls.stream().mapToDouble(UseDtl::getAmount).sum();

        WorkOrder wo = new WorkOrder();

        // 正常消耗
        wo.setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.OUT_ORDER_KEY))
                .setDirection(GlobalConsts.ORDER_DIRECTION_OUT)
                .setBusDate(new Date()).setBusUser(UserUtils.currentUser()!=null ?UserUtils.currentUser().getName() :"")
                .setBusUserCode(UserUtils.currentUser()!=null ?UserUtils.currentUser().getWorkNo() :"")
                .setBusType(WorkOrderType.OUT_USE)
                .setFlagConsignment(orderKey.consignment).setFlagOmoc(orderKey.omoc)
                .setRefId(use.getId()).setRefKey(use.getUseKey()).setRefTable("dept_use")
                .setSupplierId(supplier.getId()).setSupplierName(supplier.getName())
                .setWarehouseId(use.getWarehouseId()).setWarehouseName(use.getWarehouseName())
                .setDeliveryman(UserUtils.currentUser()!=null ?UserUtils.currentUser().getName():"")
                .setAmount(sum)
                .setReagentTeamId(use.getReagentTeamId())
                .setPurchaseOrderType(StringUtils.isNotEmpty(use.getReagentTeamId())? PurchaseType.REAGENT.getKey() : PurchaseType.MATR.getKey())
                .setDeptId(use.getDeptId()).setDeptName(use.getDeptName())
                .setRemark(String.format("由消耗单%s转换而来", use.getUseKey()))
                .setFlowStatus(GlobalConsts.FLOW_END_VALUE).setFlowModified(use.getFlowModified()).setFlowModifier(use.getFlowModifier())

        ;
        if(GlobalConsts.YES.equals(use.getFlagUseRedType())){ // 冲红单据
            wo.setDirection(GlobalConsts.ORDER_DIRECTION_IN).setBusType(WorkOrderType.IN_USE_RED);
        }
        workOrderMapper.insert(wo);

        for (UseDtl useDtl : useDtls) {
            String stockId = useDtl.getStockId();
            Stock stock = stockService.getByIdWithZero(stockId);
            if (stock == null) {
                log.error("库存不存在，SN：{}，RFID：{}，StockId：{}",
                        useDtl.getSnNo(), useDtl.getRfid(), stockId);
                throw new BusinessException("库存不存在，可能是由于数据错误");
            }
            WorkOrderItem orderItem = new WorkOrderItem();
            String[] ignoreFields = Arrays.stream(DataEntity.class.getDeclaredFields()).map(Field::getName).collect(Collectors.toList()).toArray(new String[]{});
            BeanUtils.copyProperties(stock, orderItem, ignoreFields);
            orderItem.setStockId(stockId).setAmount(useDtl.getAmount()).setPackageQty(useDtl.getPackageQty()).setSkuQty(useDtl.getSkuQty());
            orderItem.setWorkOrderId(wo.getId()).setRemark(String.format("由消耗出库单 %s 转换而来", use.getUseKey()));

            orderItem.setRefBusItemId(useDtl.getId());
            workOrderItemMapper.insert(orderItem);
        }

        return wo;
    }

    @Override
    public void preview(String id, HttpServletResponse response) {

        response.setContentType(MediaType.APPLICATION_PDF_VALUE);

        Use use = super.getById(id);
        if (use == null) {
            return;
        }


        PdfExportParams exportParams = new PdfExportParams();
        exportParams.setTitle(String.format("%s消耗单", use.getDeptName()));
        exportParams.setPerRowsOfGrid(10);
        exportParams.setPageDirection(PdfPageDirection.TRANSVERSE);
        exportParams.setWatermark("本公司");


        exportParams.addHeaderItem("科室", use.getDeptName(), 6)
                .addHeaderItem("消耗日期", use.getUseDate(), 6)
                .addHeaderItem("消耗类型", use.getUseType(), 6)
                .addHeaderItem("消耗金额", use.getAmount(), 6)
        ;

        String s = ParameterUtils.getString(ParamKeys.DEPT_USE_PRINT, "0");
        // 供应商打印
        if ("1".equals(s)){
            exportParams.addGridColumn("rowIndex", "序号", 1)
                    .addGridColumn("supplierName", "供应商", 4)
                    .addGridColumn("matrName", "品名", 4)
                    .addGridColumn("matrSpec", "品规", 4)
                    .addGridColumn("matrUnit", "单位", 2)
                    .addGridColumn("lot", "批号", 1)
                    .addGridColumn("skuQty", "数量", 1)
                    .addGridColumn("skuPrice", "单价", 1)
                    .addGridColumn("amount", "金额", 2)
                    .addGridColumn("user", "取用人", 2)
                    .addGridColumn("useTime", "取用时间", 3)
            ;
        } else{
            exportParams.addGridColumn("rowIndex", "序号", 1)
                    .addGridColumn("matrName", "品名", 5)
                    .addGridColumn("matrSpec", "品规", 5)
                    .addGridColumn("matrUnit", "单位", 2)
                    .addGridColumn("lot", "批号", 1)
//                .addGridColumn("qtyIn", "厂商", 2)
//                .addGridColumn("qtyOut", "效期", 2)
//                .addGridColumn("qtyOut", "注册证号", 2)
                    .addGridColumn("skuQty", "数量", 2)
                    .addGridColumn("skuPrice", "单价", 2)
                    .addGridColumn("amount", "金额", 2)
                    .addGridColumn("user", "取用人", 2)
                    .addGridColumn("useTime", "取用时间", 2)
            ;
        }


        List<UseDtl> useDtlList = useDtlService.list(new QueryWrapper<UseDtl>().eq("use_id", id));
        List<String> stockIds = useDtlList.stream().map(o -> o.getStockId()).collect(Collectors.toList());
        List<Stock> stockList = stockService.list(Wrappers.<Stock>query().in("id", stockIds));
        Map<String, Stock> stockMap = stockList.stream().collect(Collectors.toMap(o -> o.getId(), o -> o, (o1, o2) -> o1));
        useDtlList.stream().forEach(o -> o.setSupplierName(stockMap.get(o.getStockId()).getSupplierName()));
        if (useDtlList.size() > 0) {
            exportParams.setGridData(useDtlList);
        }

        exportParams.addFooterItem("制单人", use.getCreator(), 8)
                .addFooterItem("经办人", use.getModifier(), 8)
                .addFooterItem("科室签字:", "", 8);

        try {
            PdfExportUtils.export(response.getOutputStream(), exportParams);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 订单标识，用来作为转换订单时的标识
     */
    @EqualsAndHashCode
    @AllArgsConstructor
    private class WorkOrderKey {
        private String supplierId;
        private boolean consignment;
        private boolean omoc;
    }

    @Override
    public Map getDeptUse(String code){
         Use use = baseMapper.selectOne(Wrappers.<Use>query()
                .eq("use_key", code));
        if (use == null) {
            throw new BusinessException("该消耗单未找到！");
        }
        List<UseDtl> useDtls = useDtlService.list(Wrappers.<UseDtl>query()
                .eq("use_id", use.getId()));
        Map result = new HashMap();
        result.put("use", use);
        result.put("useItems", useDtls);
        return result;
    }

    @Override
    public Use createByFsd(FsdUser fsdUser, Warehouse warehouse, Location location, Dept dept, boolean flagUseRed, JSONArray rfidArr) {
        //1、创建主表
        Use use = new Use();

        use.setUseType("CABINET")
                .setFlagUseRedType(flagUseRed ? 1 : 0)
                .setUseKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.DEPT_USE_KEY))
                .setWarehouseId(warehouse.getId())
                .setWarehouseName(warehouse.getName())
                .setLocationId(location.getId())
                .setLocationName(location.getName())
                .setDeptId(dept.getId())
                .setDeptName(dept.getName())
                .setRemark("智能柜定数包消耗明细通知")
                .setUseDate(Calendar.getInstance().getTime())
                .setUserName(fsdUser.getUserName())
                //流程状态
                .setFlowStatus(GlobalConsts.FLOW_END_VALUE)
                .setFlowModifier(fsdUser.getUserName())
                .setFlowModified(LocalDateTime.now())
                .setCreator(fsdUser.getUserName());
        this.save(use);

        List<Stock> stocks = Lists.newArrayList();
        //创建明细
        for (Object ob : rfidArr) {
            JSONObject rfidOb = JSONObject.parseObject(JSON.toJSONString((ob)));
            String rfid = rfidOb.getString("rfid");
            List<Stock> stockListByUniqueCode = stockService.getStockListByUniqueCode(rfid);
            if (!stockListByUniqueCode.isEmpty()) {
                stocks.addAll(stockListByUniqueCode);
            }
        }
        if (stocks.isEmpty()) {
            throw new BusinessException("未找到任何库存记录");
        }
        useDtlService.saveByStockIds(stocks.stream().map(Stock::getId).collect(Collectors.toList()), use.getId(), warehouse.getId(), true);
        handlerRedUseFlowEnd(use, "");
        return use;
    }
}
